/* 
CPSC 323 - Lexical Analysis
Katie Soto
Chelsea Gunderson
12/2011
*/
//top down parser - Recursive Descent Parser (RDP)

#ifndef SYNTAX_H
#define SYNTAX_H

#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <windows.h> 

using namespace std;

//********FUNCTIONS & VARIABLES:*************
	void printMe(string rule);
	string getToken();
	void printSyntaxError(string expected);

	void Rat11F();					//<Rat11F> ::= # <Opt Function Definitions> # <Opt 
										//Declaration List> <Statement List> #
	void OptFunctionDefinitions();	//<Opt Function Definitions> ::= <Function Definitions>
										//| <Empty>
	void FunctionDefinitions();		//<Function Definitions> ::= <Function><Function 
										//DefinitionsPrime>
	void FunctionDefinitionsPrime();//<Function DefinitionsPrime> ::= <Function 
										//Definitions> | epsilon
	void Function();				//<Function> ::= function <Identifier> (<Opt Parameter
										//List> ) <Opt Declaration List> <Body>
	void OptParameterList();		//<Opt Parameter List> ::= <Parameter List> | <Empty>
	void ParameterList();			//<Parameter List> ::= <Parameter> <Parameter 
										//ListPrime>
	void ParameterListPrime();		//<Parameter ListPrime> ::= , <Parameter List> | 
										//epsilon
	void Parameter();				//<Parameter> ::= <IDs > : <Qualifier>
	void Qualifier();				//<Qualifier> ::= int | boolean | real
	void Body();					//<Body> ::= { < Statement List> }
	void OptDeclarationList();		//<Opt Declaration List> ::= <Declaration List> 
										//| <Empty>
	void DeclarationList();			//<Declaration List> := <Declaration> ; 
										//<Declaration ListPrime>
	void DeclarationListPrime();	//<Declaration ListPrime> := <Declaration List>
										//| epsilon
	void Declaration();				//<Declaration> ::= <Qualifier><IDs>
	void IDs();						//<IDs> ::= <Identifier> <IDsPrime>
	void IDsPrime();				//<IDsPrime> ::= , <IDs> | epsilon
	void StatementList();			//<Statement List> ::= <Statement> <Statement
										//ListPrime>
	void StatementListPrime();		//<Statement ListPrime> ::= <Statement List> | epsilon
	void Statement();				//<Statement> ::= <Compound> | <Assign> | <If> | 
										//<Return> | <Write> | <Read> | <While>
	void Compound();				//<Compound> ::= { <Statement List> }
	void Assign();					//<Assign> ::= <Identifier> := <Expression> ;
	void If();						//<If> ::= if ( <Condition> ) <Statement> <IfPrime>
	void IfPrime();					//<IfPrime> ::= endif | else <Statement> endif
	void Return();					//<Return> ::= return <ReturnPrime>
	void ReturnPrime();				//<ReturnPrime> ::= ; | <Expression> ;
	void Write();					//<Write> ::= print ( <Expression>);
	void Read();					//<Read> ::= scan ( <IDs> );
	void While();					//<While> ::= while ( <Condition> ) <Statement>
	void Condition();				//<Condition> ::= <Expression> <Relop> <Expression>
	void Relop();					//<Relop> ::= = | /= | > | < | => | <=
	void Expression();				//<Expression> ::= <Term><ExpressionPrime>
	void ExpressionPrime();			//<ExpressionPrime> ::= + <Term><ExpressionPrime> 
										//| - <Term><ExpressionPrime> | epsilon
	void Term();					//<Term> ::= <Factor><TermPrime>
	void TermPrime();				//<TermPrime> ::= * <Factor><TermPrime> | 
										///<Factor><TermPrime> | epsilon
	void Factor();					//<Factor> ::= - <Primary> | <Primary>
	void Primary();					//<Primary> ::= <Identifier><Primary>  | <Integer> 
										//| ( <Expression> ) | <Real> | true | false
	void PrimaryPrime();			//<Primary> ::= [<IDs>] | epsilon
	void Empty();					//<Empty> ::= epsilon
	
	string save_lex;				//string to hold lexemes or tokens as needed
	string save_type;				//string to hold the type of a lexeme
	string addr;					//string to hold the address of a token
	string addr_save;				//needed an extra address placeholder
	string saved;				//needed an extra address placeholder
//********FUNCTION DEFINITIONS:*************
//********helper functions********
	void printMe(string rule)
	{
		if(true) 
		{
			//no, do not print to screen during assembly code instruction generation (project 3)
			//cout<<"\tRULE: "<<rule<<endl;
			resultsFile <<"\tRULE: "<<rule<<endl;
		}
	}

	void printSyntaxError(string expected, int special)
	{
		if(true) //yes, eventhough this is project is for assembly
				//code generation, I still would like to know if
				//there are errors.
		{
			if(special==0)	//almost all errors fall under this category
			{
				cout<<"ERROR: Syntax Error on Line #"<<lineNumber<<"- '"<<expected<<"' expected, got token='"<<nextToken<<"' lexeme='"<<resultsStruct.lexeme<<"' instead"<<endl;
				resultsFile <<"ERROR: Syntax Error on Line #"<<lineNumber<<"- '"<<expected<<"' expected, got token='"<<nextToken<<"' lexeme='"<<resultsStruct.lexeme<<"' instead"<<endl;
				numOfErrors++;
			}
			else if((special==1)||(special==2))	//display special error 
												//message 1/2 (they are the same)
			{
				cout<<"Error: Syntax Error on Line #"<<lineNumber<<"- '#' expected as the last line of the file, got token='"<<nextToken<<"' lexeme='"<<resultsStruct.lexeme<<"' instead"<<endl;
				resultsFile<<"Error: Syntax Error on Line #"<<lineNumber<<"- '#' expected as the last line of the file, got token='"<<nextToken<<"' lexeme='"<<resultsStruct.lexeme<<"' instead"<<endl;						
				numOfErrors++;
			}else if(special==3)			//display special error message 3
			{
				cout<<"Error: Syntax Error on Line #"<<lineNumber<<"- '#' expected after function definitions, got token='"<<nextToken<<"' lexeme='"<<resultsStruct.lexeme<<"' instead"<<endl;
				resultsFile<<"Error: Syntax Error on Line #"<<lineNumber<<"- '#' expected after function definitions, got token='"<<nextToken<<"' lexeme='"<<resultsStruct.lexeme<<"' instead"<<endl;
				numOfErrors++;
			}else if(special==4)			//display special error message 4
			{
				cout<<"Error: Syntax Error on Line #"<<lineNumber<<"- '#' expected as the first line of the file, got token='"<<nextToken<<"' lexeme='"<<resultsStruct.lexeme<<"' instead"<<endl;
				resultsFile<<"Error: Syntax Error on Line #"<<lineNumber<<"- '#' expected as the first line of the file, got token='"<<nextToken<<"' lexeme='"<<resultsStruct.lexeme<<"' instead"<<endl;
				numOfErrors++;
			}
		}
	//exit after an error?
		if(errorRecovery=="y")
		{	//do exit
			//wait a little bit before exiting
			Sleep(5000);
			exit(0);
		}else if(errorRecovery=="n"){
			//dont exit, try to continue
		}else{
			//default is exit
			cout<<"Input for error recovery not recognized. Will use default: Exit on errors."<<endl;
			//wait a little bit before exiting
			Sleep(5000);
			exit(0);
		}
	}

	string getToken(){
					dontpass=length;
					current++;
			while(current < length){
					nextToken=lexer(current);			
					while(nextToken=="ignore"){//if the token is one that we ignore, 
											//keep getting the next one until 
											//it's one that we DONT ignore
						current++;
						nextToken=lexer(current);
					}//once you have one that ISN'T "ignore", then print it out:
					if(nextToken!="ignore"){
						numberOfTokens++;
						//results are written to the output file ("output.txt")
						//in the function "writeLex()" in main.cpp	
					}
		return nextToken;
			}
	//returning "nothing" tells Rat11F that there are no more tokens.
	return "nothing";
	}

//********non terminal symbol functions********
	//There is a function for each non terminal symbol:
	
	void Rat11F()
	{ 
	//Project 3 Notes: No "meaning" to attach here
		printMe("<Rat11F> ::= # <Opt Function Definitions> # <Opt Declaration List> <Statement List> #");
		if(resultsStruct.lexeme == "#")
		{
			nextToken=getToken();	
			OptFunctionDefinitions();
				if(resultsStruct.lexeme == "#")
				{
					nextToken=getToken();
					OptDeclarationList();
					StatementList();
						if(resultsStruct.lexeme == "#")
						{
							//terminal symbol found. 
							//That should have been the last one! Let's check:
								if(nextToken!="nothing")
								{//that was the last token. So, we are done! 
								 //Everything was successful
								}else{
									//# wasn't the last token? thats wrong
									printSyntaxError("#",1);
								}
						}else{
							//print out special error:
							printSyntaxError("#",2);
						}
				}else{
					//print out special error:
					printSyntaxError("#",3);
				}
		}else{
			//print out special error:
			printSyntaxError("#",4);
			}
	}

	void OptFunctionDefinitions()
	{
	//Project 3 Notes: This function is used in "functions", which we do not
	//                 deal with in this project, so no meaning is attached
		printMe("<Opt Function Definitions> ::= <Function Definitions> | <Empty>");
		//computed first sets in this function to determine what rule to follow next
			if(resultsStruct.lexeme == "function")
			{
				FunctionDefinitions();
			}else{
			 //go to <Empty>
				Empty();
			}
	}

	void FunctionDefinitions()
	{ 
	//Project 3 Notes: This function is used in "functions", which we do not
	//                 deal with in this project, so no meaning is attached
		printMe("<Function Definitions> ::= <Function><Function Definitions Prime>");
		Function();
		FunctionDefinitionsPrime();
	}

	void FunctionDefinitionsPrime()
	{ 
	//Project 3 Notes: This function is used in "functions", which we do not
	//                 deal with in this project, so no meaning is attached
		printMe("<Function DefinitionsPrime> ::= <Function Definitions> | epsilon");
		//computed first sets in this function to determine what rule to follow next
			if(resultsStruct.lexeme == "function")
			{
				FunctionDefinitions();
			}else{
				//do nothing, this is the epsilon part.
			}
	}

	void Function()
	{ 
	//Project 3 Notes: This function is used in "functions", which we do not
	//                 deal with in this project, so no meaning is attached
		printMe("<Function> ::= function <Identifier> (<Opt Parameter List> ) <Opt Declaration List> <Body>");
	
		if(resultsStruct.lexeme == "function")
		{
			nextToken=getToken();
				if(nextToken == "identifier")
				{
					nextToken=getToken();
					if(resultsStruct.lexeme == "(")
					{
						nextToken=getToken();
							OptParameterList();
						if(resultsStruct.lexeme == ")")
						{
							nextToken=getToken();
							OptDeclarationList();
							Body();
						}else{
							printSyntaxError(")",0);
						}
					}else{
						printSyntaxError("(",0);
					}
				}else{
					printSyntaxError("identifier",0);
				}
		}else{
			printSyntaxError("function",0);
		}
	}

	void OptParameterList()
	{ 
	//Project 3 Notes: This function is used in "functions", which we do not
	//                 deal with in this project, so no meaning is attached
		printMe("<Opt Parameter List> ::= <Parameter List> | <Empty>");
		//computed first sets in this function to determine what rule to follow next
			if(nextToken == "identifier")
			{
				ParameterList();
			}else{
			 //go to <Empty>
				Empty();
			}
	}

	void ParameterList()
	{ 
	//Project 3 Notes: This function is used in "functions", which we do not
	//                 deal with in this project, so no meaning is attached
		printMe("<Parameter List> ::= <Parameter> <Parameter List Prime>");
		Parameter();
		ParameterListPrime();
	}

	void ParameterListPrime()
	{ 
	//Project 3 Notes: This function is used in "functions", which we do not
	//                 deal with in this project, so no meaning is attached
		printMe("<Parameter List Prime> ::= , <Parameter List> | epsilon");
		if(resultsStruct.lexeme == ",")
		{
			nextToken=getToken();
			ParameterList();
		}else{} //do nothing, this is the epsilon part
	}

	void Parameter()
	{
	//Project 3 Notes: This function is used in "functions", which we do not
	//                 deal with in this project, so no meaning is attached
		printMe("<Parameter> ::= <IDs > : <Qualifier>");
		IDs();
		if(resultsStruct.lexeme == ":")
		{
			nextToken=getToken();
			Qualifier();
		}else{
			printSyntaxError(":",0);
		}
	}

	void Qualifier()
	{ 
	//Project 3 Notes: Identifiers and types are inserted into
	//		 the table in the Declaration() function, not here
		printMe("<Qualifier> ::= int | boolean | real");
		//note that these are lexemes, not tokens (looking for the word,
		//not the type)
		if(resultsStruct.lexeme=="int"){
			nextToken=getToken();
		}else if(resultsStruct.lexeme=="real"){
			cout<<"Warning: 'real' type is not allowed in Project 3."<<endl;
			nextToken=getToken();
		}else if(resultsStruct.lexeme=="boolean"){
			nextToken=getToken();
		}else{
			printSyntaxError("int', 'boolean', or 'real",0);
		}
	}
	
	void Body()
	{ 
	//Project 3 Notes: This function is used in "functions", which we do not
	//                 deal with in this project, so no meaning is attached
		printMe("<Body> ::= { < Statement List> }");
		if(resultsStruct.lexeme == "{")
		{
			nextToken=getToken();
			StatementList();
			if(resultsStruct.lexeme == "}")
			{
				nextToken=getToken();
			}else{
				printSyntaxError("}",0);
			}
		}else{
			printSyntaxError("{",0);
		}
	}



	void OptDeclarationList()
	{ 
	//Project 3 Notes: There are no changes being made in this method, so
	//					there is no "meaning" to be attached.
		printMe("<Opt Declaration List> ::= <Declaration List> | <Empty>");
		//computed first sets in this function to determine what rule to follow next
		if(resultsStruct.lexeme=="int"){
			DeclarationList();
		}else if(resultsStruct.lexeme=="real"){
			cout<<"Warning: 'real' type is not allowed in Project 3."<<endl;
			DeclarationList();
		}else if(resultsStruct.lexeme=="boolean"){
			DeclarationList();
		}else{
			//go to <Empty>
				Empty();
		}

	}



	void DeclarationList()
	{ 
	//Project 3 Notes: There are no changes being made in this method, so
	//					there is no "meaning" to be attached.
		printMe("<Declaration List> := <Declaration> ; <Declaration List Prime>");
		Declaration();
		if(resultsStruct.lexeme == ";")
		{
			nextToken=getToken();
			DeclarationListPrime();
		}else{
			printSyntaxError(";",0);
		}

	}

	void DeclarationListPrime()
	{ 
	//Project 3 Notes: There are no changes being made in this method, so
	//					there is no "meaning" to be attached.
		printMe("<Declaration List Prime> := <Declaration List> | epsilon");
		//computed first sets in this function to determine what rule to follow next
		if(resultsStruct.lexeme=="int"){
			DeclarationList();
		}else if(resultsStruct.lexeme=="real"){
			cout<<"Warning: 'real' type is not allowed in Project 3."<<endl;
			DeclarationList();
		}else if(resultsStruct.lexeme=="boolean"){
			DeclarationList();
		}else{
			//do nothing, this is the epsilon part
		}
	}

	void Declaration()
	{ 
		//Project 3: inserting symbols into the symbol table
			//int a; is the example used:
		printMe("<Declaration> ::= <Qualifier><IDs>");
			//lexeme = int
		//save type to use later:
		save_lex = resultsStruct.lexeme;
		Qualifier();
			//lexeme = a
		//inserts (a, int) into the symbol table:
		insert_into_SymTable(resultsStruct.lexeme, save_lex);
		IDs();
	}

	void IDs()
	{ 
		//Project 3: This is part of a declaration statement
		//		and is inserted into the Symbol Table in
		//	declaration, nothing is left to do in this fctn
		printMe("<IDs> ::= <Identifier> <IDs Prime>");
		if(nextToken == "identifier")
		{
			nextToken=getToken();
			IDsPrime();
		}else{
			printSyntaxError("identifier",0);
		}
	}

	void IDsPrime()
	{ 
		//Project 3: inserting symbols into the symbol table
		printMe("<IDs Prime> ::= , <IDs> | epsilon");
		if(resultsStruct.lexeme == ",")
		{
	//Project 3 Notes: If there is another identifier (example: int a, b),
	//          then we need to insert that one into the symbol table also:
			nextToken=getToken();
			insert_into_SymTable(resultsStruct.lexeme, save_lex);
			IDs();
		}else{
		} //do nothing, this is the epsilon part

	}
	
	void StatementList()
	{ 
	//Project 3 Notes: There are no changes being made in this method, so
	//					there is no "meaning" to be attached.
		printMe("<Statement List> ::= <Statement> <Statement List Prime>");
		Statement();
		StatementListPrime();
	}

	void StatementListPrime()
	{ 
	//Project 3 Notes: There are no changes being made in this method, so
	//					there is no "meaning" to be attached.
		printMe("<Statement List Prime> ::= <Statement List> | epsilon");
		//computed first sets in this function to determine what rule to follow next
		if(resultsStruct.lexeme=="{"){
			StatementList();
		}else if(nextToken=="identifier"){
			StatementList();
		}else if(resultsStruct.lexeme=="if"){
			StatementList();
		}else if(resultsStruct.lexeme=="return"){
			StatementList();
		}else if(resultsStruct.lexeme=="print"){
			StatementList();
		}else if(resultsStruct.lexeme=="scan"){
			StatementList();
		}else if(resultsStruct.lexeme=="while"){
			StatementList();
		}else{
			//do nothing (this is the epsilon part)
		}
	}

	void Statement()
	{ 
	//Project 3 Notes: There are no changes being made in this method, so
	//					there is no "meaning" to be attached.
	//				   We will insert the instructions for "Read", "Write"
	//					etc when it reaches the actual function.
		printMe("<Statement> ::= <Compound> | <Assign> | <If> | <Return> | <Write> | <Read> | <While>");
		//computed first sets in this function to determine what rule to follow next
		if(resultsStruct.lexeme=="{"){
			//Project 3: Compound does nothing.
			Compound();
		}else if(nextToken=="identifier"){
			Assign();
		}else if(resultsStruct.lexeme=="if"){
			If();
		}else if(resultsStruct.lexeme=="return"){
			Return();
		}else if(resultsStruct.lexeme=="print"){
			Write();
		}else if(resultsStruct.lexeme=="scan"){
			Read();
		}else if(resultsStruct.lexeme=="while"){
			While();
		}
	}

	void Compound()
	{ 
	//Project 3: We do need to assign meaning here but the
	//           meaning here is do nothing, so there
	//			 are no additions.
		printMe("<Compound> ::= { <Statement List> }");
		
		if(resultsStruct.lexeme == "{")
		{
			nextToken=getToken();
			StatementList();
			if(resultsStruct.lexeme == "}")
			{
				nextToken=getToken();
			}else{
				printSyntaxError("}",0);
			}
		}else{
			printSyntaxError("{",0);
		}

	}

	void Assign()
	{ 
	//Project 3 Notes: Assignment Statement
		printMe("<Assign> ::= <Identifier> := <Expression> ;");
		
		if(nextToken=="identifier")
		{
				save_lex = resultsStruct.lexeme;
			//save type to make sure they match later (in <Primary>)
				save_type = get_id_type(resultsStruct.lexeme);
				nextToken=getToken();
			if(resultsStruct.lexeme == ":=")
			{
				nextToken=getToken();
				Expression();
	//Project 3: get address and generate instruction:		
				addr = get_instr_address(save_lex);
				gen_instr("POPM", addr);
					if(resultsStruct.lexeme == ";")
					{
						nextToken=getToken();
					}else{
						printSyntaxError(";",0);
					}
			}else{
				printSyntaxError(":=",0);
			}
		}else{
			printSyntaxError("identifier",0);
		}
	}
	
	void If()
	{ 
		//Project 3 Notes: Our 'If/else' statement assembly code generates as so:
		/*
		...
		#6  ...if condition
		#7  JUMPZ to 'else'	if false		(10)
		#8  //do stuff within the 'if' condition
		#9  JUMP to the end of 'else'		(12)
		#10 LABEL. this is the start of 'else'
		#11 //do stuff within the 'else' condition
		#12 LABEL. this is the end of 'else' (endif)
		...
		*/
		//Project 3 Notes: Our 'If' statement assembly code generates as so:
		/*
		...
		#6  ...if condition
		#7  JUMPZ to the end of 'if' if false		(10)
		#8  //do stuff within the 'if' condition
		#9  JUMP to 'endif'							(10) <-- this line (9) isn't needed for "if" but IS needed for "if/else" so it seems a bit pointless for just "if". however, it is not harmful for just "if" statements and the code still works.
		#10 LABEL. this is the end of 'if' (endif)    
		...
		*/
		printMe("<If> ::= if ( <Condition> ) <Statement> <If Prime>");
		if(resultsStruct.lexeme == "if")
		{
			nextToken=getToken();
			if(resultsStruct.lexeme == "(")
			{
				nextToken=getToken();
				//Project 3 Notes:
				//save type. For example if(a < 5),
				//we need to save the type of "a" and
				//match it wil the type of "5".
				save_type=get_id_type(resultsStruct.lexeme);
				Condition();
				if(resultsStruct.lexeme == ")")
				{
					nextToken=getToken();
					//the "Jump" for this instruction (jump to endif
					//if condition is false) is generated in <condition>
					Statement();
					IfPrime();
					back_patch_special (get_current_inst_address(), saved);
					gen_instr("LABEL", "");
				}else{
					printSyntaxError(")",0);
				}
			}else{
				printSyntaxError("(",0);
			}
		}else{
			printSyntaxError("if",0);
		}
	}

	
	void IfPrime()
	{ 
		//Project 3 Notes: part of 'If' statement (jump & back patch)
		//				   see If() for a more elaborate explanation
		printMe("<If Prime> ::= endif | else <Statement> endif");
		saved=get_current_inst_address();
		gen_instr("JUMP", "");
		if(resultsStruct.lexeme == "endif")
		{
			nextToken=getToken();
			back_patch(get_current_inst_address());
		}else if(resultsStruct.lexeme == "else")
		{	
			back_patch(get_current_inst_address());
			gen_instr("LABEL", "");
			nextToken=getToken();
			Statement();
			if(resultsStruct.lexeme == "endif")
			{
				nextToken=getToken();
			}else{
				printSyntaxError("endif",0);
			}
		}else{
			printSyntaxError("endif",0);
		}
	}

	void Return()
	{ 
	//Project 3 Notes: This function is used in "functions", which we do not
	//                 deal with in this project, so no meaning is attached
		printMe("<Return> ::= return <Return Prime>");
		if(resultsStruct.lexeme == "return")
		{
			nextToken=getToken();
			ReturnPrime();
		}else{
			printSyntaxError("return",0);
		}
	}


	void ReturnPrime()
	{ 
	//Project 3 Notes: This function is used in "functions", which we do not
	//                 deal with in this project, so no meaning is attached
		printMe("<Return Prime> ::= ; | <Expression> ;");
		if(resultsStruct.lexeme == ";")
		{
			nextToken=getToken();
		}else{
			Expression();
			if(resultsStruct.lexeme == ";")
			{
				nextToken=getToken();
			}else{
			printSyntaxError(";",0);
			}
		}
	}

	void Write()
	{ 
	//Project 3: Need to assign meaning to the function print
	//			 which simply prints to screen (STDOUT)
		printMe("<Write> ::= print ( <Expression>);");
		if(resultsStruct.lexeme == "print")
		{
			nextToken=getToken();
				if(resultsStruct.lexeme == "(")
				{
					nextToken=getToken();
					//if this token is one of the acceptable types:
					if((nextToken == "int")||(nextToken == "boolean"))
					{
						//then save that type
						save_type=nextToken;
					}else if(nextToken == "identifier"){
						save_type=get_id_type(resultsStruct.lexeme);
					}
					Expression();
					gen_instr("STDOUT", "");
					if(resultsStruct.lexeme == ")")
					{
						nextToken=getToken();
						if(resultsStruct.lexeme == ";")
						{
							nextToken=getToken();
						}else{
							printSyntaxError(";",0);
						}
					}else{
						printSyntaxError(")",0);
					}
				}else{
					printSyntaxError("(",0);
				}
		}else{
			printSyntaxError("print",0);
		}
	}

	void Read()
	{ 
	//Project 3: Need to assign meaning to the function scan
	//			 which reads input (STDIN)
		printMe("<Read> ::= scan ( <IDs> );");
		if(resultsStruct.lexeme == "scan")
		{
			nextToken=getToken();
				if(resultsStruct.lexeme == "(")
				{
					nextToken=getToken();
					IDs();
					gen_instr("STDIN", "");
					if(resultsStruct.lexeme == ")")
					{
						nextToken=getToken();
						if(resultsStruct.lexeme == ";"){
							nextToken=getToken();
						}else{
							printSyntaxError(";",0);
						}
					}else{
						printSyntaxError(")",0);
					}
				}else{
					printSyntaxError("(",0);
				}
		}else{
			printSyntaxError("scan",0);
		}
	}

	void While()
	{ 
	//Project 3: Need to attach meaning here to jump out of the
	//			loop if condition has been met (with JUMP)
		printMe("<While> ::= while ( <Condition> ) <Statement>");
		if(resultsStruct.lexeme == "while")
		{
			//Project 3: get address of current instruction from table
			addr_save = get_current_inst_address();
			gen_instr("LABEL", "");
			nextToken=getToken();
				if(resultsStruct.lexeme == "(")
				{
					nextToken=getToken();
					//Project 3 Notes:
					//save type. For example while(a < 5),
					//we need to save the type of "a" and
					//match it wil the type of "5".
					save_type = get_id_type(resultsStruct.lexeme);
					Condition();
					if(resultsStruct.lexeme == ")")
					{
						nextToken=getToken();
						Statement();
						gen_instr("JUMP", addr_save);
						back_patch(get_current_inst_address());
						gen_instr("LABEL", "");
					}else{
						printSyntaxError(")",0);
					}
				}else{
					printSyntaxError("(",0);
				}
		}else{
			printSyntaxError("while",0);
		}
	}

	void Condition()
	{ 
		//Project 3 Notes: part of If statement (jump & back patch)
		printMe("<Condition> ::= <Expression> <Relop> <Expression>");
		Expression();
		//save relational operator for later
		save_lex = resultsStruct.lexeme;
		Relop();
		Expression();
		if(save_lex=="<"){
			gen_instr("LES", "");
			push_jumpstack(get_current_inst_address());
			gen_instr("JUMPZ", "");
		}else if(save_lex==">"){
			gen_instr("GRT", "");
			push_jumpstack(get_current_inst_address());
			gen_instr("JUMPZ", "");
		}else if(save_lex=="="){
			gen_instr("EQU", "");
			push_jumpstack(get_current_inst_address());
			gen_instr("JUMPZ", "");
		}else if(save_lex=="=>"){
			gen_instr("GEQ", "");
			push_jumpstack(get_current_inst_address());
			gen_instr("JUMPZ", "");
		}else if(save_lex=="<="){
			gen_instr("LEQ", "");
			push_jumpstack(get_current_inst_address());
			gen_instr("JUMPZ", "");
		}else if(save_lex=="/="){
			gen_instr("NEQ", "");
			push_jumpstack(get_current_inst_address());
			gen_instr("JUMPZ", "");
		}else{
			cout<<"Error: Relational operator of '"<<save_lex<<"' is not recognized."<<endl;
		}
	}

	void Relop()
	{ 
		//Project 3 Notes: The Relop instruction generation
		//				   is done in <Condition>. Here, though
		//				   we check for booleans tring to use
		//				   relational operators.
		printMe("<Relop> ::= = | /= | > | < | => | <=");
		if(resultsStruct.lexeme == "="){
			nextToken=getToken();
		}else if(resultsStruct.lexeme == "/="){
				if(save_type=="boolean")
				{
					cout<<"Error: No relational operators are allowed for booleans (line number "<<lineNumber<<")."<<endl;
					//wait a little bit before exiting
						Sleep(5000);
						exit(0);
				}
			nextToken=getToken();
		}else if(resultsStruct.lexeme == ">"){
			if(save_type=="boolean")
				{
					cout<<"Error: No relational operators are allowed for booleans (line number "<<lineNumber<<")."<<endl;
					//wait a little bit before exiting
						Sleep(5000);
						exit(0);
				}
			nextToken=getToken();
		}else if(resultsStruct.lexeme == "<"){
			if(save_type=="boolean")
				{
					cout<<"Error: No relational operators are allowed for booleans (line number "<<lineNumber<<")."<<endl;
					//wait a little bit before exiting
						Sleep(5000);
						exit(0);
				}
			nextToken=getToken();
		}else if(resultsStruct.lexeme == "=>"){
			if(save_type=="boolean")
				{
					cout<<"Error: No relational operators are allowed for booleans (line number "<<lineNumber<<")."<<endl;
					//wait a little bit before exiting
						Sleep(5000);
						exit(0);
				}
			nextToken=getToken();
		}else if(resultsStruct.lexeme == "<="){
			if(save_type=="boolean")
				{
					cout<<"Error: No relational operators are allowed for booleans (line number "<<lineNumber<<")."<<endl;
					//wait a little bit before exiting
						Sleep(5000);
						exit(0);
				}
			nextToken=getToken();
		}else{
			//any relational operator is expected:
			printSyntaxError("a Relational Operator (= | /= | > | < | => | <=)",0);
		}
	}

	void Expression()
	{ 
	//Project 3 Notes: There are no changes being made in this method, so
	//					there is no "meaning" to be attached.
		printMe("<Expression> ::= <Term><Expression Prime>");
		Term();
		ExpressionPrime();
	}

	void ExpressionPrime()
	{ 
	//Project 3 Notes: Part of the assignment statements.
		printMe("<Expression Prime> ::= + <Term><Expression Prime> | - <Term><Expression Prime> | epsilon");
		if(resultsStruct.lexeme == "+")
		{
			if(save_type=="boolean")
			{
					cout<<"Error: No arithmetic operations are allowed for booleans (line number "<<lineNumber<<")."<<endl;
					//wait a little bit before exiting
						Sleep(5000);
						exit(0);
			}
			nextToken=getToken();
			Term();
			gen_instr("ADD","");
			ExpressionPrime();
		}else if(resultsStruct.lexeme =="-"){
			if(save_type=="boolean")
			{
					cout<<"Error: No arithmetic operations are allowed for booleans (line number "<<lineNumber<<")."<<endl;
					//wait a little bit before exiting
						Sleep(5000);
						exit(0);
			}
			nextToken=getToken();
			Term();
			gen_instr("SUB","");
			ExpressionPrime();
		}else{}//skip it don't do anything (epsilon part)
	}

	void Term()
	{ 
	//Project 3 Notes: There are no changes being made in this method, so
	//					there is no "meaning" to be attached.
		printMe("<Term> ::= <Factor><Term Prime>");
		Factor();
		TermPrime();
	}

	void TermPrime()
	{ 
	//Project 3 Notes: Part of the assignment statements.
		printMe("<Term Prime> ::= * <Factor><Term Prime> | /<Factor><Term Prime> | epsilon");
		if(resultsStruct.lexeme == "*")
		{
			if(save_type=="boolean")
			{
			cout<<"Error: No arithmetic operations are allowed for booleans (line number "<<lineNumber<<")."<<endl;
			//wait a little bit before exiting
				Sleep(5000);
				exit(0);
			}
			nextToken=getToken();
			Factor();
			gen_instr("MUL","");
			TermPrime();
		}else if(resultsStruct.lexeme == "/"){
			if(save_type=="boolean")
			{
			cout<<"Error: No arithmetic operations are allowed for booleans (line number "<<lineNumber<<")."<<endl;
			//wait a little bit before exiting
				Sleep(5000);
				exit(0);
			}
			nextToken=getToken();
			gen_instr("DIV","");
			Factor();
			TermPrime();
		}else{}//skip it don't do anything (epsilon part)
	}

	void Factor()
	{ 
	//Project 3 Notes: There are no changes being made in this method, so
	//					there is no "meaning" to be attached.
		printMe("<Factor> ::= - <Primary> | <Primary>");
		if(resultsStruct.lexeme == "-")
		{
			nextToken=getToken();
			gen_instr("PUSHI", "-1");
			Primary();
			gen_instr("MUL", "");
		}else{
			Primary();
		}
	}

	void Primary()
	{ 
		//Project 3: check types in this function with save_type.
		printMe("<Primary> ::= <Identifier><Primary Prime> | <Integer> | ( <Expression> ) | <Real> | true | false");
		if(nextToken == "identifier")     //a := a;
		{
			addr = get_instr_address(resultsStruct.lexeme);
			gen_instr("PUSHM", addr);
				if(save_type!=(get_id_type(resultsStruct.lexeme)))
				{ //if types do NOT match, then error
					cout<<"Error: type '"<<save_type<<"' does not match type '"<<(get_id_type(resultsStruct.lexeme))<<"' of '"<<resultsStruct.lexeme<<"' (line number "<<lineNumber<<")"<<endl;
					//major error, stop program:	
						Sleep(5000);
						exit(0);
				}
				nextToken=getToken();
			PrimaryPrime();
		}else if(nextToken == "int")  //a := 1;
		{
				gen_instr("PUSHI", resultsStruct.lexeme);
				if(save_type!=nextToken)
				{ //if types do NOT match, then error
					cout<<"Error: type '"<<save_type<<"' does not match type '"<<nextToken<<"' of '"<<resultsStruct.lexeme<<"' (line number "<<lineNumber<<")"<<endl;
					//major error, stop program:
						Sleep(5000);
						exit(0);				
				}
				nextToken=getToken();
		}else if(resultsStruct.lexeme == "("){ //a := (1 + 2);
				nextToken=getToken();
			//don't need to check if types match, because <Expression> just loops to <Primary>
			Expression();
					if(resultsStruct.lexeme == ")"){
						nextToken=getToken();
					}else{
						printSyntaxError(")",0);
					}
		}else if(nextToken == "real") //a := 1.2;
		{
				if(save_type!=nextToken)
				{ //if types do NOT match, then error
					cout<<"Error: type '"<<save_type<<"' does not match type '"<<nextToken<<"' of "<<resultsStruct.lexeme<<" (line number "<<lineNumber<<")"<<endl;
					//major error, stop program:	
						Sleep(5000);
						exit(0);				
				}
				cout<<"Error: 'real' type is not allowed in Project 3. No instructions have been generated for "<<resultsStruct.lexeme<<"."<<endl;
				//major error, stop program:	
						Sleep(5000);
						exit(0);
			nextToken=getToken();
		}else if(resultsStruct.lexeme == "true"){ //a := true;
				if(save_type!="boolean")
				{ //if types do NOT match, then error
					cout<<"Error: type '"<<save_type<<"' does not match type '"<<"boolean"<<"' of "<<resultsStruct.lexeme<<" (line number "<<lineNumber<<")"<<endl;
					//major error, stop program:	
						Sleep(5000);
						exit(0);				
				}
			//1 = true, so push 1
			gen_instr("PUSHI", "1");
			nextToken=getToken();
		}else if(resultsStruct.lexeme == "false"){//a := false;
				if(save_type!="boolean")
				{ //if types do NOT match, then error
					cout<<"Error: type '"<<save_type<<"' does not match type '"<<"boolean"<<"' of "<<resultsStruct.lexeme<<" (line number "<<lineNumber<<")"<<endl;
					//major error, stop program:	
						Sleep(5000);
						exit(0);				
				}	
			//0 = false, so push 0
			gen_instr("PUSHI", "0");
			nextToken=getToken();
		}else{
			printSyntaxError("Identifier', 'int', '(', 'real', 'true' or 'false",0);
		}
	}

	void PrimaryPrime()
	{ 
	//Project 3 Notes: There are no changes being made in this method, so
	//					there is no "meaning" to be attached.
		printMe("<Primary Prime> ::= [<IDs>] | epsilon");
		if(resultsStruct.lexeme == "[")
		{
				nextToken=getToken();
			IDs();
			if(resultsStruct.lexeme == "]")
			{
				nextToken=getToken();
			}else{
				printSyntaxError("]",0);	
			}
		}else{}//skip it don't do anything (epsilon part)
	}

	void Empty()
	{ 
	//Project 3 Notes: There are no changes being made in this method, so
	//					there is no "meaning" to be attached.
		printMe("<Empty> ::= epsilon");
		//do nothing. This is epsilon.
	}

#endif